package com.xci.core.internal;

import cn.hutool.core.util.NumberUtil;
import com.xci.core.annotation.Authorize;
import com.xci.core.base.RestMessage;
import com.xci.core.helper.Helper;
import com.xci.core.helper.WebHelper;
import com.xci.core.setting.ApiSetting;
import com.xci.sys.entity.SysApp;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * Api接口拦截器
 *
 * @author 吕艳阳
 */
@Component
public class ApiInterceptor implements HandlerInterceptor {
    @Resource
    private ApiSetting apiSetting;

    /**
     * 在请求处理之前进行调用（Controller方法调用之前）
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果不是映射到方法直接放行
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        //appId检测
        String appId = request.getHeader(Const.HEADER_APPID_KEY);
        if (Helper.isBlank(appId) || !NumberUtil.isLong(appId)) {
            WebHelper.writeJson(RestMessage.fail("无效的应用,请按照规范请求"));
            return false;
        }
        SysApp app = Sys.me().getApp(appId);
        if (app == null) {
            WebHelper.writeJson(RestMessage.fail("无效的应用,无效应用标识"));
            return false;
        } else if (!app.getStatus()) {
            WebHelper.writeJson(RestMessage.fail("无效的应用,尚未开通服务"));
            return false;
        }
        request.setAttribute(Const.CURRENT_APP_API_KEY, app);

        //时间戳检测,确认请求是否过期
        if (apiSetting.isValidTimestamp()) {
            String timestampStr = request.getHeader(Const.HEADER_TIMESTAMP_KEY);
            if (Helper.isBlank(timestampStr) || !NumberUtil.isLong(timestampStr)) {
                WebHelper.writeJson(RestMessage.fail("无效的时间戳,请按照规范请求"));
                return false;
            }

            long start = Long.parseLong(timestampStr);
            long ts = Math.abs((System.currentTimeMillis() - start));
            if (ts > (apiSetting.getTimestampOffset() * 1000)) {
                WebHelper.writeJson(RestMessage.fail("无效的时间戳,请按照规范请求"));
                return false;
            }
        }

        //获取当前方法
        Method method = ((HandlerMethod) handler).getMethod();
        //权限检测,确认使用者是否有权限访问此功能 类/方法上有@AllowAnonymous,允许匿名登录,直接放行
        if (Helper.IsAllowAnonymous(method)) {
            return true;
        }

        //token 检测,确认登录者身份,设置request的当前用户属性
        String tokenStr = request.getHeader(Const.HEADER_TOKEN_KEY);
        if (Helper.isBlank(tokenStr)) {
            WebHelper.writeJson(RestMessage.fail("无效的用户,请按照规范请求"));
            return false;
        }

        var userResult = Sys.me().getUserByToken(tokenStr);
        if (userResult.isFail()) {
            WebHelper.writeJson(userResult);
            return false;
        }
        request.setAttribute(Const.CURRENT_USER_API_KEY, userResult.getData());

        Authorize classAuth = method.getDeclaringClass().getAnnotation(Authorize.class);
        Authorize methodAuth = method.getAnnotation(Authorize.class);
        String codes = Const.EMPTY;
        if (methodAuth != null && Helper.isNotBlank(methodAuth.code())) {
            codes = methodAuth.code();
        } else if (classAuth != null && Helper.isNotBlank(classAuth.code())) {
            codes = classAuth.code();
        }
        if (Helper.isBlank(codes)){
            return true;
        }

        if (!Sys.me().isAuthorize(userResult.getData(), codes)) {
            WebHelper.writeJson(RestMessage.fail(Sys.setting().getApi().getUnAuthorizedMessage()));
            return false;
        }
        return true;
    }
}
